/******************************************************************************* * Copyright (c) 2004, 2005 * Thomas Hallgren, Kenneth Olwing, Mitch Sonies * Pontus Rydin, Nils Unden, Peer Torngren * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the individual * copyright holders listed above, as Initial Contributors under such license. * The text of such license is available at www.eclipse.org. *******************************************************************************/ package org.eclipse.buckminster.ant.taskdefs; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.Vector; import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectHelper; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.Path; /** * <p> * Task to import another build file found as a resource in the classpath into * the current project. * <p> * It must be 'top level'. On execution it will read another Ant file into the * same Project. * <p> * Examples * * <pre> * <buckminster.importResource resource="publish.ant" /> * </pre> * * Import targets from a resource in the current classpath. * <p> */ public class ImportResource extends Task { private static void closeStream(InputStream stream) { if (stream == null) return; try { stream.close(); } catch (IOException e) { } } private static void closeStream(OutputStream stream) { if (stream == null) return; try { stream.close(); } catch (IOException e) { } } private Path classpath; private String resource; private boolean optional; /** * Adds a path to the classpath. * * @return a classpath to be configured. */ public Path createClasspath() { if (classpath == null) classpath = new Path(getProject()); return classpath.createPath(); } /** * This relies on the task order model. */ @Override public void execute() { try { if (resource == null) { throw new BuildException("import requires resource attribute"); } if (this.getOwningTarget() == null || !"".equals(getOwningTarget().getName())) { throw new BuildException("import only allowed as a top-level task"); } Project p = this.getProject(); ProjectHelper helper = (ProjectHelper) p.getReference("ant.projectHelper"); Vector<?> importStack = helper.getImportStack(); if (importStack.size() == 0) { // this happens if ant is used with a project // helper that doesn't set the import. throw new BuildException("import requires support in ProjectHelper"); } p.log("Importing resource " + resource, Project.MSG_VERBOSE); if (classpath != null) { p.log("using user supplied classpath: " + classpath, Project.MSG_DEBUG); classpath = classpath.concatSystemClasspath("ignore"); } else { classpath = new Path(p); classpath = classpath.concatSystemClasspath("only"); p.log("using system classpath: " + classpath, Project.MSG_DEBUG); } AntClassLoader loader = new AntClassLoader(p.getCoreLoader(), p, classpath, false); URL resourceURL = loader.getResource(resource); if (resourceURL == null) { String message = "Cannot find resource " + resource; if (optional) { p.log(message, Project.MSG_VERBOSE); return; } throw new BuildException(message); } File resourceFile; boolean isLocal = "file".equalsIgnoreCase(resourceURL.getProtocol()); if (isLocal) resourceFile = new File(resourceURL.getPath()); else { InputStream input = null; OutputStream output = null; try { byte[] buffer = new byte[4096]; int count; input = resourceURL.openStream(); resourceFile = File.createTempFile("import-", ".ant"); resourceFile.deleteOnExit(); output = new FileOutputStream(resourceFile); while ((count = input.read(buffer)) > 0) output.write(buffer, 0, count); } catch (IOException e) { throw new BuildException(e.getMessage()); } finally { closeStream(input); closeStream(output); } } helper.parse(p, resourceFile); if (!isLocal) resourceFile.delete(); } catch (BuildException ex) { throw ProjectHelper.addLocationToBuildException(ex, getLocation()); } } /** * Set the classpath to be used for this compilation. * * @param cp * the classpath to be used. */ public void setClasspath(Path cp) { if (classpath == null) classpath = cp; else classpath.append(cp); } /** * sets the optional attribute * * @param optional * if true ignore files that are not present, default is false */ public void setOptional(boolean optional) { this.optional = optional; } /** * the name of the resource to import. * * @param resource * the name of the resource */ public void setResource(String resource) { if (resource != null && resource.startsWith("/")) resource = resource.substring(1); this.resource = resource; } }